﻿using System;
using System.Collections.Generic;
using System.IO;
using DataFiller.DataStorage.Interpreters;
using System.Linq;

namespace DataFiller.DataStorage.Extension.ExcelOperator
{
    public static class ExcelExportOrganizer
    {
        public static Exception LastErr { get; private set; }

        /// <summary>
        /// load the template file into memory, then out put the byte array of the file that filled with corresponding data 
        /// </summary>
        /// <param name="modelRetriever">callback to retrieve data model</param>
        /// <param name="workBook">excel book object</param>
        /// <param name="result">byte array of the file had been filled</param>
        /// <param name="exportLogic">transform the filled file into byte array</param>
        /// <param name="fillLogic">fill the template file with corresponding data</param>
        /// <returns>whether export successed</returns>
        public static bool ExportExcel(RetrieveModelCallBack modelRetriever,
                                                    IExcelbook workBook,
                                                    out Byte[] result,
                                                    Func<IExcelbook, byte[]> exportLogic = null,
                                                    Action<IExcelbook, ExportContext> fillLogic = null)
        {
            if (fillLogic == null)
                fillLogic = FillTemplateFile;
            if (exportLogic == null)
                exportLogic = DoExport;

            bool success = true;
            result = null;

            try
            {
                using (var context = new ExportContext(modelRetriever))
                {
                    FillTemplateFile(workBook, context);
                    result = exportLogic(workBook);
                }
            }
            catch (Exception e)
            {
                LastErr = e;
                success = false;
            }
            return success;
        }

        #region HelperFunctions

        //transform the filled file into byte array
        public static byte[] DoExport(IExcelbook workBook)
        {
            MemoryStream ms = new MemoryStream();
            workBook.Write(ms);
            return ms.ToArray();
        }

        //fill the template file with corresponding data
        public static void FillTemplateFile(IExcelbook _templateBook, ExportContext context)
        {
            List<IExcelSheet> sheets = new List<IExcelSheet>();
            _templateBook.ForEach(sheet => sheets.Add(sheet));

            foreach (IExcelSheet sheet in sheets)
            {
                sheet.ForEach(row =>
                {
                    row.RowHandler(context);
                    row.ForEach(cell =>
                        cell.CellHandler(context)
                        );
                });

                sheet.SheetHandler(_templateBook, context);
            }
        }

        #endregion
    }
}
